package cn.iocoder.yudao.module.agent.service.user;

import cn.hutool.core.lang.Assert;
import cn.hutool.poi.excel.ExcelPicUtil;
import cn.iocoder.yudao.module.agent.controller.admin.brokerageuser.vo.AgentBrokerageUserCreateReqVO;
import cn.iocoder.yudao.module.agent.convert.base.AgentConvert;
import cn.iocoder.yudao.module.agent.convert.brokerageuser.AgentBrokerageUserConvert;
import cn.iocoder.yudao.module.agent.service.brokerageuser.AgentBrokerageUserService;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO;
import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import cn.iocoder.yudao.module.agent.controller.admin.user.vo.*;
import cn.iocoder.yudao.module.agent.dal.dataobject.user.AgentUserDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import cn.iocoder.yudao.module.agent.convert.user.AgentUserConvert;
import cn.iocoder.yudao.module.agent.dal.mysql.user.AgentUserMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.module.agent.enums.ErrorCodeConstants.*;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;

import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;

/**
 * 代理人 Service 实现类
 *
 * @author 曹建伟
 */
@Service
@Validated
public class AgentUserServiceImpl implements AgentUserService {

    @Resource
    private AgentUserMapper userMapper;

    @Resource
    private SmsCodeApi smsCodeApi;

    @Resource
    private MemberUserService memberUserService;

    @Resource
    private AgentBrokerageUserService agentBrokerageUserService;

    @Override
    public Long createUser(AgentUserCreateReqVO createReqVO) {
        // 插入
        AgentUserDO user = AgentUserConvert.INSTANCE.convert(createReqVO);
        userMapper.insert(user);
        // 返回
        return user.getId();
    }

    @Override
    public void updateUser(AgentUserUpdateReqVO updateReqVO) {
        // 校验存在
        validateUserExists(updateReqVO.getId());
        // 更新
        AgentUserDO updateObj = AgentUserConvert.INSTANCE.convert(updateReqVO);
        userMapper.updateById(updateObj);
    }

    @Override
    public void deleteUser(Long id) {
        // 校验存在
        validateUserExists(id);
        // 删除
        userMapper.deleteById(id);
    }

    private void validateUserExists(Long id) {
        if (userMapper.selectById(id) == null) {
            throw exception(USER_NOT_EXISTS);
        }
    }

    @Override
    public AgentUserDO getUser(Long id) {
        return userMapper.selectById(id);
    }

    @Override
    public AgentUserDO getByUserId(Long userId){
        return userMapper.selectOne(new LambdaQueryWrapper<AgentUserDO>()
                .eq(AgentUserDO::getUserId, userId));
    }

    @Override
    public List<AgentUserDO> getUserList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return userMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<AgentUserDO> getUserPage(AgentUserPageReqVO pageReqVO) {
        return userMapper.selectPage(pageReqVO);
    }

    @Override
    public List<AgentUserDO> getUserList(AgentUserExportReqVO exportReqVO) {
        return userMapper.selectList(exportReqVO);
    }

    @Override
    public Boolean sendSmsCode(AgentBindSmsSendReqVO reqVO){
        SmsCodeSendReqDTO smsCodeSendReqDTO = AgentConvert.INSTANCE.convertSmsSendReqDTO(reqVO.getMobile(), SmsSceneEnum.MEMBER_AGENT_BIND.getScene(), getClientIP());
        smsCodeApi.sendSmsCode(smsCodeSendReqDTO);
        return true;
    }

    @Override
    public Boolean bindBrokerageUser(AgentBindBrokerageReqVO reqVO){
        AgentUserDO agentUserDO = userMapper.selectOne(AgentUserDO::getUserId, reqVO.getAgentUserId());
        if(agentUserDO == null){
            throw exception(USER_NOT_EXISTS);
        }

        MemberUserDO brokerageUserDo = memberUserService.getUserByMobile(reqVO.getBrokerageUserMobile());
        if(brokerageUserDo == null){
            throw exception(BROKERAGE_ACCOUNT_NOT_EXISTS);
        }

        // 判断是否已经被绑定
        agentBrokerageUserService.hasBinded(agentUserDO.getUserId(), brokerageUserDo.getId());

        SmsCodeValidateReqDTO codeValidateReqDTO = AgentConvert.INSTANCE.convertSmsValidateReqVO(reqVO.getBrokerageUserMobile(), SmsSceneEnum.MEMBER_AGENT_BIND.getScene(), reqVO.getCode());
        smsCodeApi.validateSmsCode(codeValidateReqDTO);

        SmsCodeUseReqDTO smsCodeUseReqDTO = AgentConvert.INSTANCE.convertSmsUseReqVO(reqVO.getBrokerageUserMobile(), SmsSceneEnum.MEMBER_AGENT_BIND.getScene(), reqVO.getCode(), getClientIP());
        smsCodeApi.useSmsCode(smsCodeUseReqDTO);

        AgentBrokerageUserCreateReqVO brokerageUserCreateReqVO = AgentBrokerageUserConvert.INSTANCE.convert(reqVO.getAgentUserId(), brokerageUserDo.getId());
        agentBrokerageUserService.createBrokerageUser(brokerageUserCreateReqVO);

        return true;
    }

    @Override
    public Boolean bindBrokerageUserByUserId(Long agentUserId, Long brokerageUserId) {
        AgentBrokerageUserCreateReqVO brokerageUserCreateReqVO = AgentBrokerageUserConvert.INSTANCE.convert(agentUserId, brokerageUserId);
        agentBrokerageUserService.createBrokerageUser(brokerageUserCreateReqVO);

        return true;
    }

    @Override
    public void updateUserFrozenBrokerage(Long agentUserId, Integer brokerage){
        if (brokerage > 0) {
            userMapper.updateFrozenPriceIncr(agentUserId, brokerage);
        } else if (brokerage < 0) {
            userMapper.updateFrozenPriceDecr(agentUserId, brokerage);
        }
    }

    @Override
    public Boolean updateUserBrokerage(Long agentUserId, Integer brokerage) {
        if (brokerage > 0) {
            userMapper.updatePriceIncr(agentUserId, brokerage);
        } else if (brokerage < 0) {
            return userMapper.updatePriceDecr(agentUserId, brokerage) > 0;
        }
        return true;
    }

    @Override
    public void updateFrozenPriceDecrAndPriceIncr(Long userId, Integer brokerage){
        Assert.isTrue(brokerage < 0);
        int updateRows = userMapper.updateFrozenPriceDecrAndPriceIncr(userId, brokerage);
        if (updateRows == 0) {
            throw exception(BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH);
        }
    }

    @Override
    public void addWithdrawBrokerage(Long agentUserId, Integer price){
        int updateRows = userMapper.withdrawBrokerageIncr(agentUserId, price);
        if(updateRows == 0){
            throw exception(BROKERAGE_USER_INCR_ERR);
        }
    }
}
